package service

import (
	"fmt"
	"mime/multipart"
	"strconv"
	"strings"
	"trpg-base/dto"
	"trpg-base/entity"
	"trpg-common/constants"
	common_dto "trpg-common/dto"
	"trpg-common/utils/gorm_util"
	"trpg-common/utils/oss_util"
	"trpg-common/utils/time_util"
)

const defaultCoverKey = "/scripts/default_cover.jpg"

type ScriptsService struct{}

func (ScriptsService) AddOrUpdateScript(script entity.Scripts, cover *multipart.FileHeader, content *multipart.FileHeader, user common_dto.UserInfo) entity.Scripts {
	if script.LabelIds != "" {
		script.LabelIds += ","
	}
	if script.Id == 0 {
		script.IsDeleted = constants.DeleteNo
		script.Creator = user.Uid
		script.GmtCreated = time_util.Now()
		script.Modifier = user.Uid
		script.GmtModified = time_util.Now()
		gorm_util.InsertUpdateOne(&script)
	} else {
		script.Modifier = user.Uid
		script.GmtModified = time_util.Now()
	}
	// 处理cover
	coverUrl := ""
	if cover != nil {
		split := strings.Split(cover.Filename, ".")
		suffix := split[len(split)-1]
		coverPath := fmt.Sprintf("/scripts/%d/cover.%s", script.Id, suffix)
		script.CoverKey = coverPath
		coverUrl = oss_util.UploadMultiFile(cover, coverPath)
	} else {
		coverUrl = oss_util.GetUrlByKey(defaultCoverKey)
	}
	script.CoverUrl = coverUrl
	// 处理content
	contentUrl := ""
	if content != nil {
		split := strings.Split(content.Filename, ".")
		suffix := split[len(split)-1]
		contentPath := fmt.Sprintf("/scripts/%d/content.%s", script.Id, suffix)
		script.ContentKey = contentPath
		contentUrl = oss_util.UploadMultiFile(content, contentPath)
	}
	gorm_util.UpdateOneByCondition(&script)
	script.ContentUrl = contentUrl
	return script
}

func (ScriptsService) UploadCover(cover *multipart.FileHeader, id int64) string {
	split := strings.Split(cover.Filename, ".")
	suffix := split[len(split)-1]
	coverPath := fmt.Sprintf("/scripts/%d/cover.%s", id, suffix)
	scripts := entity.Scripts{}
	scripts.Id = id
	gorm_util.SelectOneByCondition(&scripts)
	scripts.CoverKey = coverPath
	gorm_util.InsertUpdateOne(&scripts)
	url := oss_util.UploadMultiFile(cover, coverPath)
	return url
}

func (ScriptsService) GetCoverUrl(id int64) string {
	scripts := entity.Scripts{}
	scripts.Id = id
	gorm_util.SelectOneByCondition(&scripts)
	return oss_util.GetUrlByKey(scripts.CoverKey)
}

func (ScriptsService) UploadContent(content *multipart.FileHeader, id int64) string {
	split := strings.Split(content.Filename, ".")
	suffix := split[len(split)-1]
	contentPath := fmt.Sprintf("/scripts/%d/content.%s", id, suffix)
	scripts := entity.Scripts{}
	scripts.Id = id
	gorm_util.SelectOneByCondition(&scripts)
	scripts.ContentKey = contentPath
	gorm_util.InsertUpdateOne(&scripts)
	url := oss_util.UploadMultiFile(content, contentPath)
	return url
}

func (ScriptsService) GetContentUrl(id int64) string {
	scripts := entity.Scripts{}
	scripts.Id = id
	gorm_util.SelectOneByCondition(&scripts)
	return oss_util.GetUrlByKey(scripts.ContentKey)
}

func (ScriptsService) GetScriptById(id int64) entity.Scripts {
	scripts := entity.Scripts{}
	scripts.Id = id
	scripts.IsDeleted = constants.DeleteNo
	gorm_util.SelectOneByCondition(&scripts)
	if scripts.CoverKey == "" {
		scripts.CoverUrl = oss_util.GetUrlByKey(defaultCoverKey)
	} else {
		scripts.CoverUrl = oss_util.GetUrlByKey(scripts.CoverKey)
	}
	if scripts.ContentKey != "" {
		scripts.ContentUrl = oss_util.GetUrlByKey(scripts.ContentKey)
	}
	// 处理label
	labelIds := make([]int64, 0)
	for _, str := range strings.Split(scripts.LabelIds, ",") {
		if str == "" {
			continue
		}
		labelId, _ := strconv.ParseInt(str, 10, 64)
		labelIds = append(labelIds, labelId)
	}
	scripts.LabelIdsArr = labelIds
	scripts.LabelNames = labelService.GetLabelNameListByIds(labelIds)
	return scripts
}

func (ScriptsService) SearchScripts(search dto.ScriptsRequest, request gorm_util.PageRequest, user common_dto.UserInfo) *gorm_util.PageResult {
	paramBuilder := gorm_util.NewParamBuilder().Model(&entity.Scripts{}).Eq("is_deleted", constants.DeleteNo)
	if search.Search != "" {
		paramBuilder.Or(gorm_util.NewParamBuilder().Like("name", `%`+search.Search+`%`), gorm_util.NewParamBuilder().Like("description", `%`+search.Search+`%`))
	}
	if search.Creator == true {
		paramBuilder.Eq("creator", user.Uid)
	} else if search.Collection == true {
		collections := make([]entity.ScriptsCollection, 0)
		gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.ScriptsCollection{}).Eq("uid", user.Uid).Eq("is_deleted", constants.DeleteNo), &collections)
		collectionIds := make([]int64, 0, len(collections))
		for _, collection := range collections {
			collectionIds = append(collectionIds, collection.ScriptId)
		}
		paramBuilder.In("id", collectionIds)
	}
	if search.LabelIds != nil && len(search.LabelIds) != 0 {
		paramSlice := make([]*gorm_util.ParamBuilder, 0, len(search.LabelIds))
		for _, labelId := range search.LabelIds {
			paramSlice = append(paramSlice, gorm_util.NewParamBuilder().Like("label_ids", `%`+strconv.FormatInt(labelId, 10)+`,%`))
		}
		paramBuilder.Or(paramSlice...)
	}
	if search.BeginTime != nil && search.EndTime != nil {
		paramBuilder.Gte("gmt_created", search.BeginTime).Lte("gmt_created", search.EndTime)
	}
	scripts := make([]entity.Scripts, 0)
	result := gorm_util.PageSelectByParamBuilder(paramBuilder, &scripts, request)
	for i, _ := range scripts {
		scripts[i].CoverUrl = oss_util.GetUrlByKey(scripts[i].CoverKey)
	}
	result.List = scripts
	return result
}

func (ScriptsService) CollectScripts(scriptId int64, user common_dto.UserInfo) {
	collection := entity.ScriptsCollection{}
	collection.ScriptId = scriptId
	collection.Uid = user.Uid
	collection.IsDeleted = constants.DeleteNo
	collection.Creator = user.Uid
	collection.Modifier = user.Uid
	collection.GmtCreated = time_util.Now()
	collection.GmtModified = time_util.Now()
	gorm_util.InsertUpdateOne(&collection)
}

func (ScriptsService) DeleteCollection(scriptId int64, user common_dto.UserInfo) {
	gorm_util.UpdateBatchByParamBuilderAndMap(
		gorm_util.NewParamBuilder().Model(&entity.ScriptsCollection{}).Eq("script_id", scriptId).Eq("uid", user.Uid).Eq("is_deleted", constants.DeleteNo),
		map[string]interface{}{
			"is_deleted":   constants.DeleteYes,
			"gmt_modified": time_util.Now(),
		})
}
